use crate::utils::config;
use chrono;
use crypto::{digest::Digest, md5::Md5};
use jsonwebtoken::{decode, encode, Algorithm, DecodingKey, EncodingKey, Header, Validation};
use serde::{Deserialize, Serialize};

#[derive(Debug, Serialize, Deserialize)]
struct Claims {
    sub: String,
    company: String,
    exp: usize,
}

pub fn validate_jwt(token: &str) -> Result<String, String> {
    let decode_key = DecodingKey::from_secret(config::CONFIG.secret().as_bytes());
    let validation = Validation::new(Algorithm::HS256);
    match decode::<Claims>(token, &decode_key, &validation) {
        Ok(token_data) => Ok(token_data.claims.sub),
        Err(e) => Err(e.to_string()),
    }
}

pub fn generate_jwt(sub: &str) -> Result<String, &str> {
    let expiration = 1000 * 60 * 60 * 24; // token 有效期为一天

    let claims = Claims {
        sub: sub.to_owned(),
        company: config::CONFIG.secret(),
        exp: (chrono::Utc::now().timestamp() + expiration) as usize,
    };

    let encoding_key = EncodingKey::from_secret(config::CONFIG.secret().as_bytes());
    let header = Header::new(Algorithm::HS256);
    let token = encode(&header, &claims, &encoding_key).unwrap();
    Ok(token)
}

pub fn md5(input: &str) -> String {
    let mut hasher = Md5::new();
    hasher.input_str(input);
    hasher.result_str()
}

#[cfg(test)]
mod tests {
    use crate::utils::crypto::{generate_jwt, validate_jwt};

    #[test]
    fn test_jwt() {
        let username = "guangbo";
        assert_eq!(
            validate_jwt(generate_jwt(username).unwrap().as_str()).unwrap(),
            username
        )
    }
}
